AWS入門ブログリレー2024〜AWS CloudFormation編〜
当エントリは弊社 AWS 事業本部による『AWS 入門ブログリレー 2024』の 26 日目のエントリです。
このブログリレーの企画は、普段 AWS サービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。
AWS をこれから学ぼう!という方にとっては文字通りの入門記事として、またすでに AWS を活用されている方にとっても AWS サービスの再発見や 2024 年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。
では、さっそくいってみましょう。今回のテーマは『AWS CloudFormation』です。
はじめに
IaC とは
まず IaC という技術を知る必要があります。
IaC(Infrastructure as Code の略)とはインフラ環境の設定やプロビジョニングをコードで管理する技術のことを指します。
簡単に言うと、料理でいうレシピに相当します。
具材は何を使って調味料は何 ml 使うかのレシピとなるものを、IaC ではテンプレート
として用意します。
IaC ツールではそのテンプレートに従ってサービスは何を使ってスペックやリソースの数はいくつかを把握し、インフラ環境を構築します。
コード管理することで、同じ環境の複製が容易になったり手動設定によるミスを減らせるといったメリットがあります。
各 IaC ツールによって構文やデプロイ方法を理解する必要があるため学習コストが発生しますが、使い方さえ理解できれば非常に便利にインフラ環境の構築ができるようになります。
AWS CloudFormation(CloudFormation)の概要
CloudFormation とは、AWS における IaC サービスです。
CloudFormation を使用することで AWS のインフラ環境の構成をコードで管理できます。
AWS CloudFormation のイメージ
もう少し、コード管理するというのを分かりやすく見ていこうと思います。
以下のような一般的な構成を考えます。
上記構成図のシステムを構築する場合、以下のリソースを作成する必要があります。
- VPC
- サブネット
- パブリックサブネット×2
- プライベートサブネット×2
- インターネットゲートウェイ
- NAT ゲートウェイ×2
- ルートテーブル
- パブリックサブネット用×1
- プライベートサブネット用×2
- ALB
- ロードバランサー
- ターゲットグループ
- EC2 インスタンス×2
- セキュリティグループ
- ALB 用×1
- EC2 インスタンス用×1
これだけのリソースをマネジメントコンソールで作成しようとすると、AWS に慣れているエンジニアでも早くても 10 分くらいはかかるんじゃないでしょうか?
これを最初 1 度だけしか作業を行わず今後一切変更もないのであれば手作業でも問題ないですが、やはり AWS でサービスを運用している以上そうもいきません。
例えば、
- 複数のアカウントに全く同じ環境を構築したい
- 災害対策のためにメインで使用するリージョンが被災した場合には、比較的早めに他のリージョンで同じ環境を構築できるようにしたい
といった場合はいかがでしょうか? 複数のアカウントに同じ環境を用意するのもなかなか手間がかかるかと思います。
そこでパッケージ商品のように CloudFormation テンプレートとして定義することで、手作業だと複雑な設定もテンプレートに沿って CloudFormation 上で自動で環境構築を行えます。
AWS CloudFormation テンプレート
では実際にここからは CloudFormation テンプレートについて見ていきます。
AWS CloudFormation で使用できるファイル形式
CloudFormation で使用できるファイル形式は、下記 2 種類をサポートしています。
- JSON
- YAML
拡張子自体は、.json、.yaml、.template、.txt などを使用できます。
JSON と YAML の違いは下記サイトが分かりやすいです。
テンプレートの構成要素
CloudFormation テンプレートを作成する際、ファイル全体ではいくつかのセクションに分かれています。
各セクションには役割があるためそれぞれ見ていきます。
セクション名 | 説明 | テンプレートへの記載が必須かどうか |
---|---|---|
AWSTemplateFormatVersion | テンプレート形式のバージョンを指定するセクション 現在時点での最新バージョンは、 2010-09-09 です |
- |
Description | テンプレートの説明を記載するセクション スタックの一覧の説明欄に表示されます |
- |
Metadata | テンプレートに対して追加情報を付与できるセクション 後述する Parameters のグループ化や cfn-init ヘルパースクリプトを使用したい際などに活用されます |
- |
Parameters | テンプレート作成、更新時に値を渡すセクション 後述する Resources と Outputs から参照できます |
- |
Rules | Parameters セクションに渡されたパラメータやパラメータの組み合わせが条件を満たしているかの検証を行うセクション 特定の環境のパラメータを指定した場合、特定のパラメータからしか選択できないようにするなどもできます。 |
- |
Mappings | キーと関連する値を対応することができるセクション 例えば特定のリージョンから特定の値を参照するなどが可能です。 |
- |
Conditions | 特定のリソースを作成または設定される条件を定義するセクション 例えばパラメータ env が prod の値を指定した場合、 |
- |
Transform | テンプレートを処理するために使用するマクロを 1 つ以上指定するセクション 例えば CloudFormation から Lambda 関数を呼び出す場合などに使われます。 |
- |
Resources | AWS リソースを宣言するセクション 基本的に AWS リソースを作成したい場合はこのセクションを使用します。 |
〇 |
Outputs | 作成したリソースを値として出力するセクション 他のスタックから値を参照したい場合に使用されます。 |
- |
Resources
セクションは必ず記載するセクションとなっているため、気を付けてテンプレートを書きましょう。
テンプレートで使用できる組み込み関数
CloudFormation テンプレートでは、関数を使用することで柔軟に値を指定したり参照することができます。
主要な組み込み関数をいくつか紹介します。
Ref
Ref を使用することで、
Parameters セクションで指定したパラメータや、作成したリソースからリソース ID を参照したい時に使用します。
Ref を使用したい場合は、!Ref
といったふうに!
を先頭に付与します。
使用例は以下です。
Parameters: InstanceTypeParameter: Type: String Default: "t2.micro" AllowedValues: - "t2.micro" - "t2.small" - "t2.medium" Description: Select the instance type for the EC2 instance Resources: MyInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceTypeParameter ImageId: ami-0abc1234567890abc ~略~
Ref で取得できる値は CloudFormation リファレンスより確認できます。
Fn::Sub
Fn::Sub を使用することで、
Ref と同様に Parameters で指定したパラメータや、作成したリソースからリソース ID や関連するパラメータを参照したい場合に使用します。
Fn::Sub を使用したい場合は、!Sub
やFn::Sub
と表現できます。
Ref との違いは以下の通りです。
- Fn::Sub で参照する場合は
${}
を付ける - 文字列の中に変数として組み込むことができる
- 例) !Sub "${ProjectName}-Instance"
- 後述する Fn::GettAtt や Fn::Join の代わりとして使用できる
Fn::Sub の使用例は以下です。
Parameters: ProjectName: Type: String Default: "MyProject" Description: Enter the name of your project Resources: MyInstance: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0abc1234567890abc ~略~ Tags: - Key: Name Value: !Sub "${ProjectName}-Instance"
Fn::GetAtt
Fn:GetAtt を使用することで、
作成したリソースから特定の属性値を取得することができます。
例えば、テンプレートの中で EC2 インスタンスを作成した場合、
Fn::GetAtt を使用するとプライベート IP アドレスを取得できたり、起動している VPC ID を取得可能です。
Fn::GetAtt を使用したい場合は、!GetAtt
やFn::GetAtt
と表現できます。
Fn::GetAtt の使用例は以下です。
Parameters: ProjectName: Type: String Default: "MyProject" Description: Enter the name of your project Resources: MyInstance: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0abc1234567890abc ~略~ Tags: - Key: Name Value: !Sub "${ProjectName}-Instance" Outputs: PrivateIPAddress: Description: Private IP address of the EC2 instance Value: !GetAtt MyInstance.PrivateIp
Fn::Join
Fn::Join を使用することで、
所定の区切り文字(または空白)を使用して文字列を連結ができます。
例えば、ARN を指定したい場合に ARN に含まれるリージョン名やリソース名を別の値から引用もできます。
Fn::Join を使用したい場合は、!Join
やFn::Join
と表現できます。
Fn::Join の使用例は以下です。
Parameters: ProjectName: Type: String Default: "MyProject" Description: Enter the name of your project Resources: MyInstance: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0abc1234567890abc ~略~ Tags: - Key: Name Value: !Join - '-' - - !Ref ProjectName - Instance
他にも、
- Fn::Base64
- Fn::Cidr
- Condition functions
- Fn::FindInMap
- Fn::ForEach
- Fn::GetAZs
- Fn::ImportValue
- Fn::Length
- Fn::Select
- Fn::Split
- Fn::ToJsonString
- Fn::Transform
などが使用できます。
詳細は下記 AWS 公式ドキュメントを参照ください。
Intrinsic function reference - AWS CloudFormation
用語説明
続いてナビゲーションペインからどんな項目なのか見ていきます。
スタック
スタックでは、CloudFormation を使用しデプロイしたものの一覧が参照できます。
テンプレートによって作成されたものはスタック
という単位で管理されます。
StackSets
StackSets では、StackSets を使用してデプロイしたものの一覧が参照できます。
StackSets とは、1 つアカウントのみにデプロイするのではなく、 複数のアカウント、複数のリージョンまたは Organizatios 配下のアカウントなど、複数の環境に同時にデプロイしたい場合に使用されます。
アカウントのベースラインとなるものを同時にデプロイおよび管理したい場合に有用です。
StackSets についてはこちらも参照ください。
エクスポート
エクスポートでは、Outputs セクションで出力された値の一覧を参照できます。
Outputs で出力された値は、Fn:ImportValue で参照可能なため、クロススタックに共通の値を参照したい場合はエクスポートの項目を参照してください、
Application Composer
CloudFormation のコンソール画面における Application Composer は、CloudFormation コンソールモードで Application Composer を利用できるものです。
まず Application Composer とは、簡単に言うと GUI ベースでサーバレス構成のモデリングできるサービスです。
こちらでは、Application Composer を CloudFormation コンソールモードで利用できるものとなっています。
詳細は以下ブログをご参照ください。
IaC ジェネレーター
IaC ジェネレーターでは、既存リソースを読み取り CloudFormation テンプレートを生成してくれる機能です。
JSON または YAML で出力が可能です。
詳細は以下ブログをご参照ください。
パブリック拡張機能
パブリック拡張機能では、全ての CloudFormation ユーザーが使用できる CloudFormation レジストリを参照することができます。
CloudFormation レジストリとは、CloudFormation を拡張し、CloudFormation でサポートされていない AWS サービスやサードパーティのサービスを管理できるようにする機能です。
アクティブ化済みの拡張機能
アクティブ化済みの拡張機能では、先述したパブリック拡張機能の中で有効化したものや、プライベートに公開されたプライベート拡張機能の一覧を参照できます。
パブリッシャー
パブリッシャーでは、拡張機能を公開したい場合の登録を行うことができます。
スポットライト
スポットライトでは、CloudFormation に関するお役立ち情報の一覧が参照できます。
ドキュメントやブログだけでなく YouTube に投稿されたポッドキャストなど様々なコンテンツを参照できるためキャッチアップに役立ちます。
CloudFormation の料金
下記名前空間となるリソースプロバイダーを使用する場合は、基本的に無料で使用できます。
- AWS::*
- Alexa::*
- Custom::*
そのため上記以外の名前空間を持つリソースプロバイダーの場合は、ハンドラーオペレーション(リソースの作成・更新・削除・読込・参照などのアクション)が下記の場合に料金が発生します。
項目 | 料金体系 |
---|---|
無料利用枠 | 1,000 件のハンドラーオペレーション/月/アカウント |
ハンドラーオペレーション | ハンドラーオペレーションごとに 0.0009 USD |
ハンドラーオペレーションの呼び出し時間 | 1 秒あたり 0.00008 USD |
また、CloudFormation フックも同様にコストが発生し、呼び出しの数と時間によって料金が発生します。(料金は上記と同じです。)
詳細は下記ページをご参照ください。
AWS CloudFormation の制限事項
CloudFormation ではいくつか制限事項(上限)があります。
例えば、テンプレート本文のサイズの上限で、51,200 バイト
で、引き上げできない制限事項となります。
そのため、ここまで大きいファイルとなってしまった場合には、スタックをネスト化させるなどし複数のテンプレートい分離することを検討してください。
ネストについては下記ブログをご参照ください。
他には、各リソースのオペレーションにはタイムアウトが存在しています。
公式ドキュメントによると、タイムアウト値は、リソースと使用する認証情報によって異なり、サービスロールを使用することでタイムアウト値を延長が可能のようです。
CloudFormation のその他の上限および制限事項などについては下記を参照ください。
AWS CloudFormation のクォータ - AWS CloudFormation Troubleshooting CloudFormation - AWS CloudFormation
やってみた
下記にサンプルテンプレートがあるためこちらを使用します。
Sample templates - AWS CloudFormation
コードを展開する
AWSTemplateFormatVersion: "2010-09-09" Mappings: RegionMap: us-east-1: AMI: "ami-0ff8a91507f77f867" us-west-1: AMI: "ami-0bdb828fd58c52235" us-west-2: AMI: "ami-a0cfeed8" eu-west-1: AMI: "ami-047bb4163c506cd98" sa-east-1: AMI: "ami-07b14488da8ea02a0" ap-southeast-1: AMI: "ami-08569b978cc4dfa10" ap-southeast-2: AMI: "ami-09b42976632b27e9b" ap-northeast-1: AMI: "ami-06cd52961ce9f0d85" Parameters: EnvType: Description: Environment type. Default: test Type: String AllowedValues: [prod, dev, test] ConstraintDescription: must specify prod, dev, or test. Conditions: CreateProdResources: !Equals [!Ref EnvType, prod] CreateDevResources: !Equals [!Ref EnvType, "dev"] Resources: EC2Instance: Type: "AWS::EC2::Instance" Properties: ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI] InstanceType: !If [CreateProdResources, c1.xlarge, !If [CreateDevResources, m1.large, m1.small]] MountPoint: Type: "AWS::EC2::VolumeAttachment" Condition: CreateProdResources Properties: InstanceId: !Ref EC2Instance VolumeId: !Ref NewVolume Device: /dev/sdh NewVolume: Type: "AWS::EC2::Volume" Condition: CreateProdResources Properties: Size: 100 AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
上記を任意のテキストファイル sample.template
に保存します。
CloudFormation のコンソール画面へ遷移し、「スタックの作成」を押下します。
「テンプレートのアップロード」を選択し、「ファイルの選択」を押下、
先ほどのテンプレートをアップロードし、「次へ」を押下します。
任意のスタック名を入力しenvType
は今回好きなものを選択し「次へ」を押下します。
興味ある方は、ここで envType を切り替えることでどんな違いがあるかをテンプレートから調べてみてください。
次のページはデフォルトのままで大丈夫なため「次へ」を押下します。
最後のページは確認画面となるため特に指定がなければ「送信」を押下するとスタックの作成が開始されます。
しばらく待つと EC2 インスタンスのコンソールで EC2 インスタンスが 1 台起動しているのが分かります。 envType の選択画面によってインスタンスタイプは以下のようになります。
- test ・・・ m1.small
- dev ・・・ m1.large
- prod ・・・ c1.xlarge
このままだと課金されてしまうため、スタックを削除し、作成したリソースをまとめて削除します。
スクリーンショット上の「削除」を押下します。
削除の確認が出るため「削除」を押下すると削除が開始します。
最後に、スタック名の論理 ID が、DELETE_COMPLETE
になっていれば削除完了です。
リファレンス
- aws-cloudformation/aws-cloudformation-templates: A collection of useful CloudFormation templates
- Template anatomy - AWS CloudFormation
- [AWS Black Belt Online Seminar] AWS CloudFormation
終わりに
以上、『AWS 入門ブログリレー 2024』の 25 日目のエントリ『AWS CloudFormation』編でした。
次回、4/20 は弊社石川覚による「Amazon Redshift編」の予定です!